home *** CD-ROM | disk | FTP | other *** search
/ The Utilities Experience / The Utilities Experience - Volume 1.iso / software / misc / o-z / x-windows / mesa-amiwin / src / glx.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-03  |  24.7 KB  |  1,012 lines

  1. /* glx.c */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  1.2
  6.  * Copyright (C) 1995  Brian Paul  (brianp@ssec.wisc.edu)
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25. $Id: glx.c,v 1.38 1995/11/30 00:20:20 brianp Exp $
  26.  
  27. $Log: glx.c,v $
  28.  * Revision 1.38  1995/11/30  00:20:20  brianp
  29.  * changed version strings to 1.2.5
  30.  *
  31.  * Revision 1.37  1995/11/20  20:49:47  brianp
  32.  * check for HP color recovery atom before choosing 8-bit Pseudo over TrueColor
  33.  *
  34.  * Revision 1.36  1995/11/03  17:39:08  brianp
  35.  * changed visual->class to visual->c_class for C++
  36.  *
  37.  * Revision 1.35  1995/11/01  15:13:40  brianp
  38.  * renamed all class variables per Steven Spitz
  39.  *
  40.  * Revision 1.34  1995/10/14  16:31:52  brianp
  41.  * don't make copy of XVisualInfo anymore
  42.  * cleaned up some code, bumped version string to 1.2.4
  43.  *
  44.  * Revision 1.33  1995/09/20  18:21:15  brianp
  45.  * support for 4-bit visuals added
  46.  *
  47.  * Revision 1.32  1995/09/15  18:52:32  brianp
  48.  * updated version strings to 1.2.3
  49.  *
  50.  * Revision 1.31  1995/09/05  19:59:17  brianp
  51.  * glXCreateContext() accepts non-glXChooseVisual() visuals per Wolfram Gloger
  52.  *
  53.  * Revision 1.30  1995/09/05  15:35:48  brianp
  54.  * bitcount() was incorrect
  55.  * changed find_glx_visual() to match IDs per Armin Liebchen
  56.  *
  57.  * Revision 1.29  1995/08/24  14:30:08  brianp
  58.  * try to match root visual in get_visual(), per Asif Khan
  59.  * pick 8-bit PseudoColor before 8-bit TrueColor in choose_x_visual()
  60.  *
  61.  * Revision 1.28  1995/08/01  20:56:39  brianp
  62.  * lots of new GL/X visual handling code
  63.  *
  64.  * Revision 1.27  1995/07/24  21:38:36  brianp
  65.  * changed choose_x_visual() to start with 8-bit CI depths
  66.  *
  67.  * Revision 1.26  1995/07/24  20:35:20  brianp
  68.  * replaced memset() with MEMSET() and memcpy() with MEMCPY()
  69.  *
  70.  * Revision 1.25  1995/07/24  18:56:49  brianp
  71.  * added GrayScale and StaticGray support
  72.  * new choose_x_visual() algorithm
  73.  * glXGetConfig(GLX_DEPTH_SIZE) returns bits, not bytes
  74.  *
  75.  * Revision 1.24  1995/07/06  20:14:01  brianp
  76.  * added DirectColor support to glXChooseVisual()
  77.  *
  78.  * Revision 1.23  1995/06/12  15:29:06  brianp
  79.  * search for CI visuals from shallowest to deepest per GLX_BUFFER_SIZE
  80.  *
  81.  * Revision 1.22  1995/06/09  21:48:22  brianp
  82.  * changed version string to 1.2.1
  83.  *
  84.  * Revision 1.21  1995/05/24  13:00:15  brianp
  85.  * updated version query functions to return 1.2
  86.  *
  87.  * Revision 1.20  1995/05/22  21:02:41  brianp
  88.  * Release 1.2
  89.  *
  90.  * Revision 1.19  1995/05/22  16:44:48  brianp
  91.  * added over/underlay error checking
  92.  *
  93.  * Revision 1.18  1995/05/19  14:22:18  brianp
  94.  * added MESA_BACK_BUFFER environment variable
  95.  *
  96.  * Revision 1.17  1995/05/16  19:19:46  brianp
  97.  * added casts to allow compiling with OpenGL's glx.h header
  98.  * implemented GLX_color_SIZE attributes in glXGetConfig()
  99.  *
  100.  * Revision 1.16  1995/05/15  15:48:21  brianp
  101.  * added share_list support to glXCreateContext
  102.  *
  103.  * Revision 1.15  1995/05/10  19:01:29  brianp
  104.  * Better glXGetConfig() support from Armin Liebchen
  105.  *
  106.  * Revision 1.14  1995/04/17  14:40:07  brianp
  107.  * Changed XMesaAttachTo... to XMesaBind...
  108.  *
  109.  * Revision 1.13  1995/04/17  14:31:26  brianp
  110.  * GLXPixmaps implemented
  111.  * uses new XMesaCreateContext() API
  112.  *
  113.  * Revision 1.12  1995/04/13  19:49:12  brianp
  114.  * added SGI's multi-sample extension for GLX 1.1
  115.  *
  116.  * Revision 1.11  1995/04/11  13:40:35  brianp
  117.  * better GLX visual handling
  118.  * introduced GLX 1.1 functions
  119.  *
  120.  * Revision 1.10  1995/03/30  21:09:44  brianp
  121.  * added 8-bit TrueColor test
  122.  *
  123.  * Revision 1.9  1995/03/27  20:33:12  brianp
  124.  * added MESA_RGB_VISUAL, MESA_CI_VISUAL environment variable support
  125.  *
  126.  * Revision 1.8  1995/03/24  15:16:52  brianp
  127.  * replaced ACCUM_BITS with ACC_TYPE
  128.  *
  129.  * Revision 1.7  1995/03/13  15:58:04  brianp
  130.  * removed glXUseXFont stub
  131.  *
  132.  * Revision 1.6  1995/03/08  18:51:21  brianp
  133.  * check if ctx is NULL in glXMakeCurrent per Thorsten Olh
  134.  *
  135.  * Revision 1.5  1995/03/07  19:10:19  brianp
  136.  * look at color/index depth arguments when selecting the visual
  137.  *
  138.  * Revision 1.4  1995/03/04  19:29:44  brianp
  139.  * 1.1 beta revision
  140.  *
  141.  * Revision 1.3  1995/03/04  19:18:17  brianp
  142.  * new visual selection code
  143.  *
  144.  * Revision 1.2  1995/03/01  17:05:00  brianp
  145.  * added error check to glXSwapBuffers
  146.  *
  147.  * Revision 1.1  1995/02/28  21:23:25  brianp
  148.  * Initial revision
  149.  *
  150.  */
  151.  
  152.  
  153. /*
  154.  * A pseudo-GLX implementation to allow OpenGL/GLX programs to work with Mesa.
  155.  *
  156.  * Thanks to the contributors:
  157.  *
  158.  * Initial version:  Philip Brown (philb@CSUA.Berkeley.EDU)
  159.  * Better glXGetConfig() support: Armin Liebchen (liebchen@asylum.cs.utah.edu)
  160.  * Further visual-handling refinements: Wolfram Gloger
  161.  *    (wmglo@Dent.MED.Uni-Muenchen.DE).
  162.  */
  163.  
  164.  
  165.  
  166. #include <stdio.h>
  167. #include <stdlib.h>
  168. #include <string.h>
  169. #include <X11/Xlib.h>
  170. #include <X11/Xutil.h>
  171. #include "GL/gl.h"
  172. #include "GL/glx.h"
  173. #include "GL/xmesa.h"
  174. #include "xmesaP.h"
  175. #include "config.h"
  176. #include "context.h"
  177. #include "dd.h"
  178.  
  179. /*
  180.  * Since we don't have a real GLX extension, the XVisualInfo doesn't
  181.  * carry all the info we need such as double buffer mode, depth buffer, etc.
  182.  * We use a table to associate this extra information with each XVisualInfo
  183.  * structure we encounter in glXChooseVisual() or glXGetConfig().
  184.  */
  185. struct glx_visual {
  186.     Display *dpy;
  187.     XVisualInfo *visinfo;        /* The X information */
  188.     GLboolean rgba_buffer_flag;    /* RGBA mode? */
  189.     GLboolean double_buffer_flag;    /* double buffered? */
  190.     GLboolean depth_buffer_flag;    /* depth buffer? */
  191. };
  192.  
  193. #define MAX_VISUALS 100
  194.  
  195. static struct glx_visual VisualTable[MAX_VISUALS];
  196. static int NumVisuals = 0;
  197.  
  198.  
  199.  
  200. /*
  201.  * We also need to keep a list of Pixmaps created with glXCreateGLXPixmap()
  202.  * so when glXMakeCurrent() is called we know if the drawable is a pixmap
  203.  * or a window.
  204.  */
  205. #define MAX_PIXMAPS 10
  206. static Pixmap PixmapList[MAX_PIXMAPS];
  207. static int NumPixmaps = 0;
  208.  
  209.  
  210.  
  211.  
  212.  
  213.  
  214. /*
  215.  * Given an XVisualInfo and RGB, Double, and Depth buffer flags, save the
  216.  * configuration in our list of GLX visuals.
  217.  */
  218. static void save_glx_visual( Display *dpy, XVisualInfo *vinfo,
  219.                              GLboolean rgba, GLboolean dbl, GLboolean depth )
  220. {
  221.    if (NumVisuals+1<MAX_VISUALS) {
  222.       VisualTable[NumVisuals].dpy = dpy;
  223.       VisualTable[NumVisuals].visinfo = vinfo;
  224.       VisualTable[NumVisuals].rgba_buffer_flag = rgba;
  225.       VisualTable[NumVisuals].double_buffer_flag = dbl;
  226.       VisualTable[NumVisuals].depth_buffer_flag = depth;
  227.       NumVisuals++;
  228.    }
  229.    else {
  230.       fprintf( stderr, "GLX Error: maximum number of visuals exceeded\n");
  231.    }
  232. }
  233.  
  234.  
  235.  
  236. /*
  237.  * Find the GLX visual associated with an XVisualInfo then return the
  238.  * RGBA, double-buffering, and depth-buffer flags.
  239.  */
  240. static GLboolean find_glx_visual( Display *dpy, XVisualInfo *vinfo,
  241.                   GLboolean *rgba,
  242.                   GLboolean *dbl,
  243.                   GLboolean *depth )
  244. {
  245.    int i;
  246.  
  247.    /* First try to match pointers */
  248.    for (i=0;i<NumVisuals;i++) {
  249.       if (VisualTable[i].dpy==dpy && VisualTable[i].visinfo==vinfo) {
  250.      *rgba  = VisualTable[i].rgba_buffer_flag;
  251.      *dbl   = VisualTable[i].double_buffer_flag;
  252.      *depth = VisualTable[i].depth_buffer_flag;
  253.      return GL_TRUE;
  254.       }
  255.    }
  256.    /* try to match visual id */
  257.    for (i=0;i<NumVisuals;i++) {
  258.       if (VisualTable[i].dpy==dpy
  259.           && VisualTable[i].visinfo->visualid == vinfo->visualid) {
  260.      *rgba  = VisualTable[i].rgba_buffer_flag;
  261.      *dbl   = VisualTable[i].double_buffer_flag;
  262.      *depth = VisualTable[i].depth_buffer_flag;
  263.      return GL_TRUE;
  264.       }
  265.    }
  266.    return GL_FALSE;
  267. }
  268.  
  269.  
  270.  
  271. /*
  272.  * Test if the given XVisualInfo is usable for Mesa rendering.
  273.  */
  274. static GLboolean is_usable_visual( XVisualInfo *vinfo )
  275. {
  276. #if defined(__cplusplus) || defined(c_plusplus)
  277.    switch (vinfo->c_class) {
  278. #else
  279.    switch (vinfo->class) {
  280. #endif
  281.       case StaticGray:
  282.       case GrayScale:
  283.          /* Any StaticGray/GrayScale visual works in RGB or CI mode */
  284.          return GL_TRUE;
  285.       case StaticColor:
  286.       case PseudoColor:
  287.      /* Any StaticColor/PseudoColor visual of at least 4 bits */
  288.      if (vinfo->depth>=4) {
  289.         return GL_TRUE;
  290.      }
  291.      else {
  292.         return GL_FALSE;
  293.      }
  294.       case TrueColor:
  295.       case DirectColor:
  296.      /* Any depth of TrueColor or DirectColor works in RGB mode */
  297.      return GL_TRUE;
  298.       default:
  299.      /* This should never happen */
  300.      return GL_FALSE;
  301.    }
  302. }
  303.  
  304.  
  305.  
  306.  
  307. /*
  308.  * Try to get an X visual which matches the given arguments.
  309.  */
  310. static XVisualInfo *get_visual( Display *dpy, int scr,
  311.                     unsigned int depth, int xclass )
  312. {
  313.    XVisualInfo temp;
  314.    long mask;
  315.    int n;
  316.    int default_depth;
  317.    int default_class;
  318.  
  319.    mask = VisualScreenMask | VisualDepthMask | VisualClassMask;
  320.    temp.screen = scr;
  321.    temp.depth = depth;
  322. #if defined(__cplusplus) || defined(c_plusplus)
  323.    temp.c_class = xclass;
  324. #else
  325.    temp.class = xclass;
  326. #endif
  327.  
  328.    default_depth = DefaultDepth(dpy,scr);
  329. #if defined(__cplusplus) || defined(c_plusplus)
  330.    default_class = DefaultVisual(dpy,scr)->c_class;
  331. #else
  332.    default_class = DefaultVisual(dpy,scr)->class;
  333. #endif
  334.  
  335.    if (depth==default_depth && xclass==default_class) {
  336.       /* try to get root window's visual */
  337.       temp.visualid = DefaultVisual(dpy,scr)->visualid;
  338.       mask |= VisualIDMask;
  339.    }
  340.  
  341.    return XGetVisualInfo( dpy, mask, &temp, &n );
  342. }
  343.  
  344.  
  345.  
  346. /*
  347.  * Retrieve the value of the given environment variable and find
  348.  * the X visual which matches it.
  349.  * Input:  dpy - the display
  350.  *         screen - the screen number
  351.  *         varname - the name of the environment variable
  352.  * Return:  an XVisualInfo pointer to NULL if error.
  353.  */
  354. static XVisualInfo *get_env_visual( Display *dpy, int scr, char *varname )
  355. {
  356.    char *value;
  357.    char type[100];
  358.    int depth, xclass = -1;
  359.    XVisualInfo *vis;
  360.  
  361.    value = getenv( varname );
  362.    if (!value) {
  363.       return NULL;
  364.    }
  365.  
  366.    sscanf( value, "%s %d", type, &depth );
  367.  
  368.    if (strcmp(type,"TrueColor")==0)          xclass = TrueColor;
  369.    else if (strcmp(type,"DirectColor")==0)   xclass = DirectColor;
  370.    else if (strcmp(type,"PseudoColor")==0)   xclass = PseudoColor;
  371.    else if (strcmp(type,"StaticColor")==0)   xclass = StaticColor;
  372.    else if (strcmp(type,"GrayScale")==0)     xclass = GrayScale;
  373.    else if (strcmp(type,"StaticGray")==0)    xclass = StaticGray;
  374.  
  375.    if (xclass>-1 && depth>0) {
  376.       vis = get_visual( dpy, scr, depth, xclass );
  377.       if (vis) {
  378.      return vis;
  379.       }
  380.    }
  381.  
  382.    fprintf( stderr, "Mesa: GLX unable to find visual class=%s, depth=%d.\n",
  383.         type, depth );
  384.    return NULL;
  385. }
  386.  
  387.  
  388.  
  389. /*
  390.  * Select an X visual which satisfies the RGBA/CI flag and minimum depth.
  391.  * Input:  dpy, screen - X display and screen number
  392.  *         rgba - GL_TRUE = RGBA mode, GL_FALSE = CI mode
  393.  *         min_depth - minimum visual depth
  394.  * Return:  pointer to an XVisualInfo or NULL.
  395.  */
  396. static XVisualInfo *choose_x_visual( Display *dpy, int screen,
  397.                      GLboolean rgba, int min_depth )
  398. {
  399.    XVisualInfo *vis;
  400.    int xclass, visclass;
  401.    int depth;
  402.  
  403.    if (rgba) {
  404.       Atom hp_cr_maps = XInternAtom(dpy, "_HP_RGB_SMOOTH_MAP_LIST", True);
  405.       /* First see if the MESA_RGB_VISUAL env var is defined */
  406.       vis = get_env_visual( dpy, screen, "MESA_RGB_VISUAL" );
  407.       if (vis) {
  408.      return vis;
  409.       }
  410.       /* Otherwise, search for a suitable visual */
  411.       for (xclass=0;xclass<6;xclass++) {
  412.      switch (xclass) {
  413.         case 0:  visclass = TrueColor;    break;
  414.         case 1:  visclass = DirectColor;  break;
  415.         case 2:  visclass = PseudoColor;  break;
  416.         case 3:  visclass = StaticColor;  break;
  417.         case 4:  visclass = GrayScale;    break;
  418.         case 5:  visclass = StaticGray;   break;
  419.      }
  420.      if (min_depth==0) {
  421.         /* start with shallowest */
  422.         for (depth=0;depth<=24;depth++) {
  423.                if (visclass==TrueColor && depth==8 && !hp_cr_maps) {
  424.                   /* Special case:  try to get 8-bit PseudoColor before */
  425.                   /* 8-bit TrueColor */
  426.                   vis = get_visual( dpy, screen, 8, PseudoColor );
  427.                   if (vis) {
  428.                      return vis;
  429.                   }
  430.                }
  431.            vis = get_visual( dpy, screen, depth, visclass );
  432.            if (vis) {
  433.           return vis;
  434.            }
  435.         }
  436.      }
  437.      else {
  438.         /* start with deepest */
  439.         for (depth=24;depth>=min_depth;depth--) {
  440.                if (visclass==TrueColor && depth==8 && !hp_cr_maps) {
  441.                   /* Special case:  try to get 8-bit PseudoColor before */
  442.                   /* 8-bit TrueColor */
  443.                   vis = get_visual( dpy, screen, 8, PseudoColor );
  444.                   if (vis) {
  445.                      return vis;
  446.                   }
  447.                }
  448.            vis = get_visual( dpy, screen, depth, visclass );
  449.            if (vis) {
  450.           return vis;
  451.            }
  452.         }
  453.      }
  454.       }
  455.    }
  456.    else {
  457.       /* First see if the MESA_CI_VISUAL env var is defined */
  458.       vis = get_env_visual( dpy, screen, "MESA_CI_VISUAL" );
  459.       if (vis) {
  460.      return vis;
  461.       }
  462.       /* Otherwise, search for a suitable visual, starting with shallowest */
  463.       for (xclass=0;xclass<4;xclass++) {
  464.      switch (xclass) {
  465.         case 0:  visclass = PseudoColor;  break;
  466.         case 1:  visclass = StaticColor;  break;
  467.         case 2:  visclass = GrayScale;    break;
  468.         case 3:  visclass = StaticGray;   break;
  469.      }
  470.      /* try 8-bit up through 16-bit */
  471.      for (depth=8;depth<=16;depth++) {
  472.         vis = get_visual( dpy, screen, depth, visclass );
  473.         if (vis) {
  474.            return vis;
  475.         }
  476.      }
  477.      /* try min_depth up to 8-bit */
  478.      for (depth=min_depth;depth<8;depth++) {
  479.         vis = get_visual( dpy, screen, depth, visclass );
  480.         if (vis) {
  481.            return vis;
  482.         }
  483.      }
  484.       }
  485.    }
  486.  
  487.    /* didn't find a visual */
  488.    return NULL;
  489. }
  490.  
  491.  
  492. /*
  493.  * Return the number of bits set in n.
  494.  */
  495. static int bitcount( unsigned long n )
  496. {
  497.    int bits;
  498.    for (bits=0; n>0; n=n>>1) {
  499.       if (n&1) {
  500.          bits++;
  501.       }
  502.    }
  503.    return bits;
  504. }
  505.  
  506.  
  507.  
  508. XVisualInfo *glXChooseVisual( Display *dpy, int screen, int *list )
  509. {
  510.    int *parselist;
  511.    XVisualInfo *vis;
  512.    int min_depth = 0;
  513.    int min_ci = 0;
  514.    int min_red=0, min_green=0, min_blue=0, min_alpha=0;
  515.    GLboolean rgba_flag = GL_FALSE;
  516.    GLboolean double_flag = GL_FALSE;
  517.    GLboolean depth_flag = GL_FALSE;
  518.  
  519.    parselist = list;
  520.  
  521.    while (*parselist) {
  522.  
  523.       switch (*parselist) {
  524.      case GLX_USE_GL:
  525.         /* ignore */
  526.         parselist++;
  527.         break;
  528.      case GLX_BUFFER_SIZE:
  529.         parselist++;
  530.         min_ci = *parselist++;
  531.         break;
  532.      case GLX_LEVEL:
  533.         /* ignore */
  534.         parselist++;
  535.         if (*parselist!=0) {
  536.            /* Overlays/underlays not supported */
  537.            return NULL;
  538.         }
  539.         parselist++;
  540.         break;
  541.      case GLX_RGBA:
  542.         rgba_flag = GL_TRUE;
  543.         parselist++;
  544.         break;
  545.      case GLX_DOUBLEBUFFER:
  546.         double_flag = GL_TRUE;
  547.         parselist++;
  548.         break;
  549.      case GLX_STEREO:
  550.         /* ignore */
  551.         parselist++;
  552.         break;
  553.      case GLX_AUX_BUFFERS:
  554.         /* ignore */
  555.         parselist++;
  556.         parselist++;
  557.         break;
  558.      case GLX_RED_SIZE:
  559.         parselist++;
  560.         min_red = *parselist++;
  561.         break;
  562.      case GLX_GREEN_SIZE:
  563.         parselist++;
  564.         min_green = *parselist++;
  565.         break;
  566.      case GLX_BLUE_SIZE:
  567.         parselist++;
  568.         min_blue = *parselist++;
  569.         break;
  570.      case GLX_ALPHA_SIZE:
  571.         /* ignore */
  572.         parselist++;
  573.         min_alpha = *parselist++;
  574.         break;
  575.      case GLX_DEPTH_SIZE:
  576.         depth_flag = GL_TRUE;
  577.         parselist++;
  578.         min_depth = *parselist++;
  579.         break;
  580.      case GLX_STENCIL_SIZE:
  581.         /* silently ignore */
  582.         parselist++;
  583.         parselist++;
  584.         break;
  585.      case GLX_ACCUM_RED_SIZE:
  586.      case GLX_ACCUM_GREEN_SIZE:
  587.      case GLX_ACCUM_BLUE_SIZE:
  588.      case GLX_ACCUM_ALPHA_SIZE:
  589.         /* silently ignore */
  590.         parselist++;
  591.         parselist++;
  592.         break;
  593.      case GLX_SAMPLES_SGIS:
  594.         /* silently ignored */
  595.         parselist++;
  596.         parselist++;
  597.         break;
  598.      case GLX_SAMPLE_BUFFER_SGIS:
  599.         /* silently ignored */
  600.         parselist++;
  601.         parselist++;
  602.         break;
  603.      case None:
  604.         break;
  605.      default:
  606.         /* undefined attribute */
  607.         return NULL;
  608.       }
  609.    }
  610.  
  611.    /*
  612.     * Since we're only simulating the GLX extension this function will never
  613.     * find any real GL visuals.  Instead, all we can do is try to find an RGB
  614.     * or CI visual of appropriate depth.  Other requested attributes such as
  615.     * double buffering, depth buffer, etc. will be associated with the X
  616.     * visual and stored in the VisualTable[].
  617.     */
  618.    if (rgba_flag) {
  619.       /* Get an RGB visual */
  620.       int min_rgb = min_red + min_green + min_blue;
  621.       if (min_rgb>1 && min_rgb<8) {
  622.      /* a special case to be sure we can get a monochrome visual */
  623.      min_rgb = 1;
  624.       }
  625.       vis = choose_x_visual( dpy, screen, rgba_flag, min_rgb );
  626.    }
  627.    else {
  628.       /* Get a colormapped visual */
  629.       vis = choose_x_visual( dpy, screen, rgba_flag, min_ci );
  630.    }
  631.  
  632.    if (vis) {
  633.       save_glx_visual( dpy, vis, rgba_flag, double_flag, depth_flag );
  634.    }
  635.  
  636.    return vis;
  637. }
  638.  
  639.  
  640.  
  641.  
  642. GLXContext glXCreateContext( Display *dpy, XVisualInfo *visinfo,
  643.                  GLXContext share_list, Bool direct )
  644. {
  645.    XMesaContext ctx;
  646.    GLboolean ximage_flag = GL_TRUE;
  647.    GLboolean rgba_flag, double_flag, depth_flag;
  648.  
  649.    if (!find_glx_visual(dpy, visinfo, &rgba_flag, &double_flag, &depth_flag)) {
  650.       /* This visual wasn't found with glXChooseVisual() */
  651.       if (is_usable_visual( visinfo )) {
  652.          /* Configure this visual as RGB, double-buffered, depth-buffered. */
  653.          /* This is surely wrong for some people's needs but what else */
  654.          /* can be done?  They should use glXChooseVisual(). */
  655.          rgba_flag = GL_TRUE;
  656.          double_flag = GL_TRUE;
  657.          depth_flag = GL_TRUE;
  658.          save_glx_visual( dpy, visinfo, rgba_flag, double_flag, depth_flag );
  659.       }
  660.       else {
  661.          fprintf(stderr,"Mesa: error in glXCreateContext: bad visual\n");
  662.          return NULL;
  663.       }
  664.    }
  665.  
  666.    if (double_flag) {
  667.       /* Check if the MESA_BACK_BUFFER env var is set */
  668.       char *backbuffer = getenv("MESA_BACK_BUFFER");
  669.       if (backbuffer) {
  670.          if (backbuffer[0]=='p' || backbuffer[0]=='P') {
  671.             ximage_flag = GL_FALSE;
  672.          }
  673.          else if (backbuffer[0]=='x' || backbuffer[0]=='X') {
  674.             ximage_flag = GL_TRUE;
  675.          }
  676.          else {
  677.             fprintf(stderr, "Mesa: invalid value for MESA_BACK_BUFFER ");
  678.             fprintf(stderr, "environment variable, using an XImage.\n");
  679.          }
  680.       }
  681.    }
  682.  
  683.    ctx = XMesaCreateContext( dpy, visinfo, rgba_flag, double_flag,
  684.                     ximage_flag, (XMesaContext) share_list );
  685.    return (GLXContext) ctx;
  686. }
  687.  
  688.  
  689.  
  690. Bool glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx )
  691. {
  692.    if (ctx && drawable) {
  693.       /* determine if the drawable is a GLXPixmap */
  694.       GLuint i;
  695.       GLboolean pixmap_flag = GL_FALSE;
  696.       for (i=0;i<NumPixmaps;i++) {
  697.      if (PixmapList[i]==drawable) {
  698.         pixmap_flag = GL_TRUE;
  699.         break;
  700.      }
  701.       }
  702.       /* Bind the XMesaContext to the pixmap or window */
  703.       if (pixmap_flag) {
  704.      if (!XMesaBindPixmap( (XMesaContext) ctx, drawable )) {
  705.         return False;
  706.      }
  707.       }
  708.       else {
  709.      if (!XMesaBindWindow( (XMesaContext) ctx, drawable )) {
  710.         return False;
  711.      }
  712.       }
  713.       /* Make the XMesaContext the current one */
  714.       if (XMesaMakeCurrent( (XMesaContext) ctx )) {
  715.      return True;
  716.       }
  717.       else {
  718.      return False;
  719.       }
  720.    }
  721.    else if (!ctx && !drawable) {
  722.       /* release current context w/out assigning new one. */
  723.       XMesaMakeCurrent( NULL );
  724.       return True;
  725.    }
  726.    else {
  727.       /* either ctx or drawable is NULL, this is an error */
  728.       return False;
  729.    }
  730. }
  731.  
  732.  
  733.  
  734. GLXPixmap glXCreateGLXPixmap( Display *dpy, XVisualInfo *visual, Pixmap pixmap )
  735. {
  736.    if (NumPixmaps==MAX_PIXMAPS) {
  737.       fprintf( stderr, "Mesa: glXCreateGLXPixmap: too many pixmaps\n");
  738.       return 0;
  739.    }
  740.    PixmapList[NumPixmaps] = pixmap;
  741.    NumPixmaps++;
  742.    return pixmap;
  743. }
  744.  
  745.  
  746. void glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap )
  747. {
  748.    int i, j;
  749.  
  750.    for (i=0;i<NumPixmaps;i++) {
  751.       if (PixmapList[i]==pixmap) {
  752.      for (j=i+1;j<MAX_PIXMAPS;j++) {
  753.         PixmapList[j-1] = PixmapList[j];
  754.      }
  755.      NumPixmaps--;
  756.      return;
  757.       }
  758.    }
  759.    fprintf( stderr, "Mesa: glXDestroyGLXPixmap: invalid pixmap\n");
  760. }
  761.  
  762.  
  763. void glXCopyContext( Display *dpy, GLXContext src, GLXContext dst,
  764.              GLuint mask )
  765. {
  766.    XMesaContext xm_src, xm_dst;
  767.    xm_src = (XMesaContext) src;
  768.    xm_dst = (XMesaContext) dst;
  769.    gl_copy_context( xm_src->gl_ctx, xm_dst->gl_ctx, mask );
  770. }
  771.  
  772.  
  773.  
  774. Bool glXQueryExtension( Display *dpy, int *errorb, int *event )
  775. {
  776.    /* Mesa's GLX isn't really an X extension but we try to act like one. */
  777.    return True;
  778. }
  779.  
  780.  
  781. void glXDestroyContext( Display *dpy, GLXContext ctx )
  782. {
  783.    XMesaDestroyContext( (XMesaContext) ctx );
  784. }
  785.  
  786.  
  787.  
  788. Bool glXIsDirect( Display *dpy, GLXContext ctx )
  789. {
  790.    /* This isn't true but... */
  791.    return True;
  792. }
  793.  
  794.  
  795.  
  796. void glXSwapBuffers( Display *dpy, GLXDrawable drawable )
  797. {
  798.    XMesaContext ctx = XMesaGetCurrentContext();
  799.    if (ctx->frontbuffer!=drawable) {
  800.       fprintf( stderr,
  801.       "Warning: glXSwapBuffers drawable doesn't match current context\n");
  802.    }
  803.    else {
  804.       XMesaSwapBuffers();
  805.    }
  806. }
  807.  
  808.  
  809.  
  810. Bool glXQueryVersion( Display *dpy, int *maj, int *min )
  811. {
  812.    /* Return GLX version, not Mesa version */
  813.    *maj = 1;
  814.    *min = 1;
  815.    return True;
  816. }
  817.  
  818.  
  819.  
  820. /*
  821.  * Query the GLX attributes of the given XVisualInfo.
  822.  */
  823. int glXGetConfig( Display *dpy, XVisualInfo *visual,
  824.           int attrib, int *value )
  825. {
  826.    GLboolean rgba_flag, double_flag, depth_flag;
  827.  
  828.    if (!find_glx_visual(dpy, visual, &rgba_flag, &double_flag, &depth_flag)) {
  829.       /* this visual wasn't obtained with glXChooseVisual */
  830.       if (is_usable_visual( visual )) {
  831.      /* Return "optimistic" values */
  832.      rgba_flag = GL_TRUE;
  833.      double_flag = GL_TRUE;
  834.      depth_flag = GL_TRUE;
  835.          save_glx_visual( dpy, visual, rgba_flag, double_flag, depth_flag );
  836.       }
  837.       else {
  838.      /* this visual can't be used for GL rendering */
  839.      if (attrib==GLX_USE_GL) {
  840.         *value = (int) False;
  841.         return 0;
  842.      }
  843.      else {
  844.         /*fprintf( stderr, "Mesa: Error in glXGetConfig: bad visual\n");*/
  845.         return GLX_BAD_VISUAL;
  846.      }
  847.       }
  848.    }
  849.  
  850.    switch(attrib) {
  851.       case GLX_USE_GL:
  852.          *value = (int) True;
  853.      return 0;
  854.       case GLX_BUFFER_SIZE:
  855.      *value = visual->depth;
  856.      return 0;
  857.       case GLX_LEVEL:
  858.      *value = 0;
  859.      return 0;
  860.       case GLX_RGBA:
  861.      if (rgba_flag) {
  862.         *value = True;
  863.      }
  864.      else {
  865.         *value = False;
  866.      }
  867.      return 0;
  868.       case GLX_DOUBLEBUFFER:
  869.      *value = (int) double_flag;
  870.      return 0;
  871.       case GLX_STEREO:
  872.      *value = (int) False;
  873.      return 0;
  874.       case GLX_AUX_BUFFERS:
  875.      *value = (int) False;
  876.      return 0;
  877.       case GLX_RED_SIZE:
  878.      {
  879.         int n = bitcount( visual->visual->red_mask );
  880.         *value = n>0 ? n : 8;
  881.      }
  882.      return 0;
  883.       case GLX_GREEN_SIZE:
  884.      {
  885.         int n = bitcount( visual->visual->green_mask );
  886.         *value = n>0 ? n : 8;
  887.      }
  888.      return 0;
  889.       case GLX_BLUE_SIZE:
  890.      {
  891.         int n = bitcount( visual->visual->blue_mask );
  892.         *value = n>0 ? n : 8;
  893.      }
  894.      return 0;
  895.       case GLX_ALPHA_SIZE:
  896.      *value = 8;
  897.      return 0;
  898.       case GLX_DEPTH_SIZE:
  899.      if (depth_flag) {
  900.         *value = 8 * sizeof( GLint );
  901.      }
  902.      else {
  903.         *value = 0;
  904.      }
  905.      return 0;
  906.       case GLX_STENCIL_SIZE:
  907.      *value = STENCIL_BITS;
  908.      return 0;
  909.       case GLX_ACCUM_RED_SIZE:
  910.       case GLX_ACCUM_GREEN_SIZE:
  911.       case GLX_ACCUM_BLUE_SIZE:
  912.       case GLX_ACCUM_ALPHA_SIZE:
  913.      *value = 8 * sizeof(ACC_TYPE);
  914.      return 0;
  915.       case GLX_SAMPLES_SGIS:
  916.      /* one sample per pixel */
  917.      *value = 1;
  918.      return 0;
  919.       case GLX_SAMPLE_BUFFER_SGIS:
  920.      /* No multi-sample buffers available */
  921.      *value = 0;
  922.      return 0;
  923.       default:
  924.      return GLX_BAD_ATTRIBUTE;
  925.    }
  926. }
  927.  
  928.  
  929.  
  930. GLXContext glXGetCurrentContext( void )
  931. {
  932.    return (GLXContext) XMesaGetCurrentContext();
  933. }
  934.  
  935.  
  936.  
  937. GLXDrawable glXGetCurrentDrawable( void )
  938. {
  939.    XMesaContext ctx;
  940.  
  941.    ctx = XMesaGetCurrentContext();
  942.    return ctx->frontbuffer;
  943. }
  944.  
  945.  
  946.  
  947. void glXWaitGL( void )
  948. {
  949.    (*DD.flush)();
  950. }
  951.  
  952.  
  953.  
  954. void glXWaitX( void )
  955. {
  956.    (*DD.flush)();
  957. }
  958.  
  959.  
  960.  
  961.  
  962. /*
  963.  * New functions in GLX version 1.1
  964.  */
  965.  
  966.  
  967. const char *glXQueryExtensionsString( Display *dpy, int screen )
  968. {
  969.    static char *extensions = "";
  970.    return extensions;
  971. }
  972.  
  973.  
  974.  
  975. const char *glXQueryServerString( Display *dpy, int screen, int name )
  976. {
  977.    static char *extensions = "";
  978.    static char *vendor = "Brian Paul";
  979.    static char *version = "1.2.5 Mesa";
  980.  
  981.    switch (name) {
  982.       case GLX_EXTENSIONS:
  983.          return extensions;
  984.       case GLX_VENDOR:
  985.      return vendor;
  986.       case GLX_VERSION:
  987.      return version;
  988.       default:
  989.          return NULL;
  990.    }
  991. }
  992.  
  993.  
  994.  
  995. const char *glXGetClientString( Display *dpy, int name )
  996. {
  997.    static char *extensions = "";
  998.    static char *vendor = "Brian Paul";
  999.    static char *version = "1.2.5 Mesa";
  1000.  
  1001.    switch (name) {
  1002.       case GLX_EXTENSIONS:
  1003.          return extensions;
  1004.       case GLX_VENDOR:
  1005.      return vendor;
  1006.       case GLX_VERSION:
  1007.      return version;
  1008.       default:
  1009.          return NULL;
  1010.    }
  1011. }
  1012.